package com.buddy.sds.common.message;

import com.buddy.sds.common.ContextHolder;
import com.buddy.sds.common.message.handler.Event;
import com.buddy.sds.common.message.handler.EventHandler;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.Map;
import java.util.concurrent.*;

@Component
@Slf4j
@Scope("singleton")
public class MessageManager {

    private BlockingQueue<Event> coreBlockingQueue = new LinkedBlockingQueue<>();


    private Multimap<Class, EventHandler> classEventHandlerMap = HashMultimap.create();

    private ExecutorService executorService = new ThreadPoolExecutor(10, 50, 1, TimeUnit.HOURS, new LinkedBlockingQueue<>());

    @Autowired
    public MessageManager(ContextHolder contextHolder) {

        classEventHandlerMap.clear();

        ApplicationContext applicationContext = contextHolder.getApplicationContext();


        if (applicationContext != null) {

            Map<String, EventHandler> handlerMap = applicationContext.getBeansOfType(EventHandler.class);

            handlerMap.forEach((k, v) -> {

                if (v.getClass().equals(EventHandler.class)) {
                    return;
                }

                if (!applicationContext.isSingleton(k)) {

                    log.error("{} 不是单例对象", v.getClass().getName());
                    return;
                }

                Class<Event> eventClass = v.supportEvent();
                if (eventClass == null) {
                    log.error("handler:{} 未提供支持的event", v.getClass().getName());
                    return;
                }

                classEventHandlerMap.put(eventClass, v);

                log.info("注册 Handler:{} for Event:{}", v.getClass().getName(), eventClass.getName());
            });


            executorService.submit(() -> {

                try {

                    while (true) {

                        Event event = coreBlockingQueue.take();

                        if (event != null) {

                            Collection<EventHandler> handler = classEventHandlerMap.get(event.getClass());

                            if (handler == null) {

                                log.error("未找到针对类型{} 的 eventHandler ", event.getClass());
                                continue;
                            }

                            executorService.submit(new Worker(handler, event));

                        }


                    }
                } catch (InterruptedException e) {
                   // e.printStackTrace();
                    log.error("消息队列发生中断异常");
                }
            });

            log.info("系统消息订阅服务已启动");

        }
    }


    /**
     * 发送消息
     *
     * @param event
     */
    public void publish(Event event) {

        if (event == null) {
            return;
        }

        coreBlockingQueue.offer(event);
    }


    private class Worker implements Runnable {

        private Collection<EventHandler> eventHandler;

        private Event event;

        public Worker(Collection<EventHandler> eventHandler, Event event) {
            this.eventHandler = eventHandler;
            this.event = event;
        }

        @Override
        public void run() {

            eventHandler.forEach(h -> {

                h.handlerMessage(event);
            });

        }
    }

}
